
/*
 * CurrentPath.h
 *
 *  Created on: Apr 12, 2012
 *      Author: falko
 */


#ifndef CURRENT_PATH_H_
#define CURRENT_PATH_H_


#include "numeric.h"
#include <vector>
#include <cstdlib>
namespace falko
{
const hpf_t PERM_FREE_SPACE = "1.25663706e-6";



class BaseCurrentPath
{
public:
	virtual ~BaseCurrentPath(){}

	virtual void getField(hpv3d_t const &point, hpv3d_t &field) = 0;

	virtual bool inContact(hpv3d_t const &point) = 0;

	virtual uint getPartitions() const {return partitions_; }

	virtual void getPoint(uint const i, hpv3d_t &point) const = 0;

	virtual void getPartitionLength(hpf_t &Length) const = 0;

	virtual hpf_t const &current() const { return current_; }

	virtual void current(hpf_t const &t) { current_ = t; }

protected:
	BaseCurrentPath() : path_center_(),
//						angular_displacement_(),
						partitions_(0),
						current_(0.0)
	{}

	hpv3d_t path_center_;
//	hpv3d_t angular_displacement_; //phi, theta, psi
	uint partitions_;
	hpf_t current_;
};


/////////////////////////////////////////////////////////////////////////////
// class Loop
//
//
/////////////////////////////////////////////////////////////////////////////
class Loop : public BaseCurrentPath
{
public:
	Loop(hpv3d_t const &center, hpf_t const &radius);

	Loop(hpv3d_t const &center, hpf_t const &radius, hpf_t const &t) : BaseCurrentPath()
	{
		path_center_ = center;
		radius_ = radius;
		partitions_ = 50;
		current_ = t;
	}

	virtual ~Loop(){}

	virtual void getField(hpv3d_t const &point, hpv3d_t &field);

	virtual bool inContact(hpv3d_t const &point);

	virtual void getPartitionLength(hpf_t &Length) const;

	virtual void getPoint(uint const i, hpv3d_t &point) const;

private:
	hpf_t radius_;
};


class MagneticField
{
public:
	MagneticField() : paths_(){}
	~MagneticField();

	void addPath(BaseCurrentPath* path, bool own = false);

	void getField(hpv3d_t const &point, hpv3d_t &field) const;

	bool inContact(hpv3d_t const &point);


private:
	struct PathPointer
	{
		PathPointer(BaseCurrentPath* path, bool own) : path_(path), own_(own){}
		BaseCurrentPath* path_;
		bool own_;
	};

	std::vector<PathPointer> paths_;
};

class PathFactory
{
public:
	static void MakeCoil(MagneticField *path,
						   uint const loops,
						   hpf_t const &wire_radius,
						   hpf_t const &length,
						   hpf_t const &coil_inner_radius,
						   hpf_t const &current,
						   hpv3d_t const &center);

	static void solve(hpv3d_t *field,
					  hpv3d_t const *point,
					  BaseCurrentPath const *path);
};


}

#endif /* CURRENT_PATH_H_ */
